﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using Ue.Extensions;

namespace Ue.Components.VerificationCode
{
    public static class VerifyCodeFactory
    {
        private const string VerifyCodeKey = "Ue.VerifyCode";

        public static VerifyCode GetVerifyCode(HttpContext context)
        {
            return VerifyCodeFactory.GetVerifyCode(context,VerifyCodeOptions.Number| VerifyCodeOptions.FontStyle);
        }
        public static VerifyCode GetVerifyCode(HttpContext context, VerifyCodeOptions options)
        {
            var backgroundComponent = options.Contains(VerifyCodeOptions.BackgroundImage)
                ? new VerifyCodeBackgroundComponent(VerifyCodeHolder.BackgroundImages)
                : new VerifyCodeBackgroundComponent();

            char[] chars ;
            if (options.Contains(VerifyCodeOptions.Letter) && options.Contains(VerifyCodeOptions.Number))
            {
                chars = VerifyCodeHolder.Number.Concat(VerifyCodeHolder.Letters).Concat(VerifyCodeHolder.Number).ToArray();
            }
            else if (options.Contains(VerifyCodeOptions.Letter))
            {
                chars = VerifyCodeHolder.Letters;
            }
            else
            {
                chars = VerifyCodeHolder.Number;
            }
            IList<IVerifyCodeCharComponents> charComponents=new List<IVerifyCodeCharComponents>(){
                new VerifyCodeCharComponentOfDraw()
            };
            if(options.Contains(VerifyCodeOptions.FontStyle)){
                charComponents.Add(new VerifyCodeCharComponentOfFontStyle());
            }

            var stringComponent = new VerifyCodeStringComponent(
                chars,
                backgroundComponent.StringColors,
                VerifyCodeHolder.FontFamilies,
                charComponents.ToArray());

            IList<IVerifyCodeComponent> components=new List<IVerifyCodeComponent>(){
                backgroundComponent,
                stringComponent
            };

            if (options.Contains(VerifyCodeOptions.InterferenceLines))
            {
                components.Add(new VerifyCodeInterferenceLinesComponent(() =>
                {
                    return stringComponent.Colours.GetRandomElement();
                }));
            }

            return VerifyCodeFactory.GetVerifyCode(context,components.ToArray());

        }
        public static VerifyCode GetVerifyCode(HttpContext context, params IVerifyCodeComponent[] verifyCodeComponents)
        {
            var verifyCode = context.Session[VerifyCodeFactory.VerifyCodeKey] as VerifyCode;

            if (verifyCode == null || !(context.Handler as System.Web.UI.Page).IsPostBack)
            {
                verifyCode = new VerifyCode(VerifyCodeFactory.Generator(verifyCodeComponents));
                context.Session[VerifyCodeFactory.VerifyCodeKey] = verifyCode;
            }

            return verifyCode;
        }

        private static VerifyImage Generator(params IVerifyCodeComponent[] verifyCodeComponents)
        {
            if (verifyCodeComponents == null || verifyCodeComponents.Length == 0)
            {
                throw new ArgumentNullException("verifyCodeComponents");
            }

            VerifyImage verifyImage = new VerifyImage();
            VerifyImageDrawContext context = new VerifyImageDrawContext();

            var orderResults = verifyCodeComponents.OrderBy(item => item.Priority);
            foreach (var item in orderResults)
            {
                item.Draw(ref context);
            }

            return context.Save();
        }
    }
}
